import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

public class FileCrawler implements Runnable {
	private final BlockingDeque<File>[] fileDequeues;
	private final FileFilter fileFilter;
	private final File root;
	CountDownLatch latch;
	ExecutorService crawlerExecutor;

	private static AtomicInteger crawlerJobCount = new AtomicInteger();

	public FileCrawler(BlockingDeque<File>[] dequeues,
			final FileFilter fileFilter, File root, CountDownLatch latch,
			ExecutorService crawlerExecutor) {
		this.fileDequeues = dequeues;
		this.root = root;
		this.fileFilter = new FileFilter() {
			public boolean accept(File f) {
				return f.isDirectory() || fileFilter.accept(f);
			}
		};
		this.latch = latch;
		this.crawlerExecutor = crawlerExecutor;
		crawlerJobCount.incrementAndGet();
	}

	private boolean alreadyIndexed(File f) {
		return false;
	}

	public void run() {
		try {
			crawl(root);
			crawlerJobCount.decrementAndGet();
			if (crawlerJobCount.get() == 0) {
				latch.countDown();
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}

	private void crawl(File root) throws InterruptedException {
		File[] entries = root.listFiles(fileFilter);
		if (entries != null) {
			for (File entry : entries)
				if (entry.isDirectory()) {
					FileCrawler crawler = new FileCrawler(fileDequeues,
							fileFilter, entry, latch, crawlerExecutor);
					crawlerExecutor.submit(crawler);
				} else if (!alreadyIndexed(entry)) {
					int index = (int) (Math.random() * fileDequeues.length);
					fileDequeues[index].put(entry);
				}
		}
	}
}